package com.library.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.library.common.config.WeChatConfig;
import com.library.common.utils.CommonUtil;
import com.library.common.utils.HttpUtils;
import com.library.entity.*;
import com.library.mapper.UserInfoMapper;
import com.library.service.RemoteBookUserService;
import com.library.service.UserInfoService;
import com.library.util.SecurityConstants;
import com.library.util.WxUntill;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Security;
import java.util.Base64;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 用户信息表 服务实现类
 * </p>
 *
 * @author dhing
 * @since 2020-12-29
 */
@Service
@Slf4j
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {
//	@Value("${system.param.defaultUserPhoto}")
//	private String defaultUserPhoto;
//
//	@Value("${system.param.defaultPassword}")
//	private String defaultPassword;

	@Autowired
	private WeChatConfig weChatConfig;
	@Autowired
	private RemoteBookUserService remoteBookUserService;

//	private BookUserService bookUserService;

	@Override
	public boolean register(String mobile, String password) {
		UserInfo user = new UserInfo();
		user.setUserId(CommonUtil.getId());
		user.setPhone(mobile);
		//user.setPassword(new MyPasswordEncoder().encode(password));
		user.setPassword(new MyPasswordEncoder().encode(password));
		//user.setUserType(UserTypeEnum.PERSON.getCode());//注册的时候默认用户类型是个人
		user.setPhotoUrl("https://img0.baidu.com/it/u=871616535,372355344&fm=253&fmt=auto&app=120&f=JPEG?w=440&h=439");
		user.setNick("用户" + user.getUserId());
		baseMapper.insert(user);
		//同时向bookuser表里面插入数据
		BookUserEntity bookUserEntity = new BookUserEntity();
		bookUserEntity.setUserName(mobile);
		//密码
		//bookUserEntity.setUserCode(new MyPasswordEncoder().encode(password));
		bookUserEntity.setPhoneNumber(mobile);
		//remoteBookUserService.saveBookUser(bookUserEntity, SecurityConstants.FROM_IN);
		return Boolean.TRUE;
	}

	@Override
	public boolean registerExt(RegisterBean registerBean) {
		UserInfo user = new UserInfo();
		user.setUserId(CommonUtil.getId());
		user.setEmail(registerBean.getEmail());
		user.setUserName(registerBean.getUserName());
		user.setName(registerBean.getName());
		user.setCompanyName(registerBean.getCompanyName());
		user.setPhone(registerBean.getMobile());
		//user.setPassword(new MyPasswordEncoder().encode(password));
		//user.setPassword(new MyPasswordEncoder().encode(registerBean.getPassword()));
		//user.setUserType(UserTypeEnum.PERSON.getCode());//注册的时候默认用户类型是个人
		user.setPhotoUrl("https://img1.baidu.com/it/u=1310564963,1641173348&fm=253&fmt=auto&app=120&f=JPEG?w=1280&h=800");
		user.setNick("用户" + user.getUserId());
		try {
			user.setOpenId(WxUntill.getWxOpenid(registerBean.getWxCode()));
		} catch (IOException e) {
			e.printStackTrace();
		}
		String decode = decode(registerBean.getBindLocation());
		terrainEntity summaryEntity = remoteBookUserService.getOne(decode.replace("\"", ""), SecurityConstants.FROM_IN);
		user.setProvinceName("河南省");
		user.setCityCode(summaryEntity.getCityCode() == null ? "" : summaryEntity.getCityCode());
		user.setAreaCode(summaryEntity.getAreaCode() == null ? "" : summaryEntity.getAreaCode());
		user.setCommitteeCode(summaryEntity.getCommitteeCode() == null ? "" : summaryEntity.getCommitteeCode());
		user.setStreetCode(summaryEntity.getStreetCode() == null ? "" : summaryEntity.getStreetCode());
		user.setCityName(summaryEntity.getCityName() == null ? "" : summaryEntity.getCityName());
		user.setAreaName(summaryEntity.getAreaName() == null ? "" : summaryEntity.getAreaName());
		user.setCommitteeName(summaryEntity.getCommitteeName() == null ? "" : summaryEntity.getCommitteeName());
		user.setStreetName(summaryEntity.getStreetName() == null ? "" : summaryEntity.getStreetName());
		baseMapper.insert(user);

		//同时向bookuser表里面插入数据
		BookUserEntity bookUserEntity = new BookUserEntity();
		bookUserEntity.setUserName(registerBean.getMobile());
		//密码
		bookUserEntity.setUserCode(new MyPasswordEncoder().encode(registerBean.getPassword()));
		bookUserEntity.setPhoneNumber(registerBean.getMobile());
		bookUserEntity.setCity(summaryEntity.getCityCode() == null ? "" : summaryEntity.getCityCode());
		bookUserEntity.setDistrict(summaryEntity.getAreaCode() == null ? "" : summaryEntity.getAreaCode());
		bookUserEntity.setCommittee(summaryEntity.getCommitteeCode() == null ? "" : summaryEntity.getCommitteeCode());
		bookUserEntity.setVillage(summaryEntity.getStreetCode() == null ? "" : summaryEntity.getStreetCode());
		remoteBookUserService.saveBookUser(bookUserEntity, SecurityConstants.FROM_IN);

		return Boolean.TRUE;
	}

	@Override
	public UserInfo getUserByPhoneAndPassword(String phone, String password) {
		UserInfo user = this.getOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getPhone, phone).eq(UserInfo::getPassword, password));
		return user;
	}

	@Override
	public UserInfo getUserByEmailAndPassword(String email, String password) {
		UserInfo user = this.getOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getEmail, email).eq(UserInfo::getPassword, password));
		return user;
	}

	@Override
	public UserInfo getUserByEmail(String email) {
		UserInfo user = this.getOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getEmail, email));
		return user;
	}

	@Override
	public boolean mobileExsit(String mobile) {
		int count = (int) this.count(new QueryWrapper<UserInfo>().eq("phone", mobile));
		return count > 0 ? Boolean.TRUE : Boolean.FALSE;
	}

	@Override
	public boolean emailExsit(String email) {
		int count = (int) this.count(new QueryWrapper<UserInfo>().eq("email", email));
		return count > 0 ? Boolean.TRUE : Boolean.FALSE;
	}

	@Override
	public boolean userNameExsit(String userName) {
		int count = (int) this.count(new QueryWrapper<UserInfo>().eq("user_name", userName));
		return count > 0 ? Boolean.TRUE : Boolean.FALSE;
	}

	@Override
	public UserInfo getUserByPhone(String phone) {
//		UserInfo user = this.getOne(new QueryWrapper<UserInfo>().eq("phone", phone));
		UserInfo user = this.getOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getPhone, phone));
		return user;
	}

	@Override
	public UserInfo getUserByUserName(String userName) {
		UserInfo user = this.getOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getUserName, userName));
		return user;
	}

	@Override
	public boolean updatePassword(String mobile, String password) {
		return this.baseMapper.updatePwdByMobile(mobile, new MyPasswordEncoder().encode(password)) > 1 ? Boolean.TRUE : Boolean.FALSE;
	}

	@Override
	public boolean updatePasswordByUserId(Long userId, String password) {
		return this.baseMapper.updatePwdByUserId(userId, new MyPasswordEncoder().encode(password)) > 1 ? Boolean.TRUE : Boolean.FALSE;
	}

	@Override
	public boolean updateMobile(String oldMobile, String newMobile) {
		return this.baseMapper.updateMobileByMobile(oldMobile, newMobile) > 1 ? Boolean.TRUE : Boolean.FALSE;
	}

	@Override
	public UserInfo getUserByUserId(Long userId) {
		return this.getOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getUserId, userId));
	}
	@Override
	public UserInfo getUserByOpenId(String openId) {
		return this.getOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getOpenId, openId));
	}

	@Override
	public int addCollect(Long id) {
		return this.baseMapper.addCollect(id);
	}

	@Override
	public int reduceCollect(Long id) {
		return this.baseMapper.reduceCollect(id);

	}


	@Override
	public List<UserInfo> getALlUsers() {
		QueryWrapper<UserInfo> wrapper = new QueryWrapper<>();
		return this.baseMapper.selectList(wrapper);
	}

	@Override
	public UserInfo saveWeChatUser(String code) {
		//Map<String,Object>resultMap=new HashMap<>();
		String accessTokenUrl = String.format(WeChatConfig.getOpenAccessTokenUrl(), weChatConfig.getOpenAppid(), weChatConfig.getOpenAppsecret(), code);

		//获取access_token
		Map<String, Object> baseMap = HttpUtils.doGet(accessTokenUrl);

		if (baseMap == null || baseMap.isEmpty()) {
			return null;
		}
		log.info("**********************************baseMap={}", JSON.toJSON(baseMap));
		String accessToken = (String) baseMap.get("access_token");
		String openId = (String) baseMap.get("openid");


		UserInfo dbUser = this.getOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getOpenId, openId));

		if (dbUser != null) { //更新用户，直接返回
			return dbUser;
		}

		//获取用户基本信息
		String userInfoUrl = String.format(WeChatConfig.getOpenUserInfoUrl(), accessToken, openId);
		//获取access_token
		Map<String, Object> baseUserMap = HttpUtils.doGet(userInfoUrl);

		if (baseUserMap == null || baseUserMap.isEmpty()) {
			return null;
		}
		log.info("**********************************baseUserMap={}", JSON.toJSON(baseUserMap));
		String nickname = (String) baseUserMap.get("nickname");

		//Double sexTemp  = (Double) baseUserMap.get("sex");
		//int sex = sexTemp.intValue();
		String province = (String) baseUserMap.get("province");
		String city = (String) baseUserMap.get("city");
		String country = (String) baseUserMap.get("country");
		String headimgurl = (String) baseUserMap.get("headimgurl");
		StringBuilder sb = new StringBuilder(country).append("||").append(province).append("||").append(city);
		String finalAddress = sb.toString();
		try {
			//解决乱码
			nickname = new String(nickname.getBytes("ISO-8859-1"), "UTF-8");
			finalAddress = new String(finalAddress.getBytes("ISO-8859-1"), "UTF-8");

		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}

		UserInfo user = new UserInfo();
		user.setNick(nickname);
		user.setWechatNick(nickname);
		user.setPhotoUrl(headimgurl);
		user.setAddressCityCode(finalAddress);
		user.setOpenId(openId);
		//user.setPhone(openId);
		user.setUserId(CommonUtil.getId());
		//user.setSex(sex);
		user.setCreateTime(new Date());
		//user.setPassword(new MyPasswordEncoder().encode(defaultPassword));
		this.baseMapper.insert(user);
		//resultMap.put("user",user);
		//resultMap.put("redirctUrl","");
		return user;
	}

	@Override
	public UserInfo bandingWechat(String code, String state) {
		UserInfo user = this.getUserByPhone(state);
		if (user == null) {
			return null;
		}
		String accessTokenUrl = String.format(WeChatConfig.getOpenAccessTokenUrl(), weChatConfig.getOpenAppid(), weChatConfig.getOpenAppsecret(), code);

		//获取access_token
		Map<String, Object> baseMap = HttpUtils.doGet(accessTokenUrl);

		if (baseMap == null || baseMap.isEmpty()) {
			return null;
		}
		log.info("**********************************baseMap={}", JSON.toJSON(baseMap));
		String accessToken = (String) baseMap.get("access_token");
		String openId = (String) baseMap.get("openid");


		UserInfo dbUser = this.getOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getOpenId, openId));

		if (dbUser != null) { //更新用户，直接返回
			return dbUser;
		}

		//获取用户基本信息
		String userInfoUrl = String.format(WeChatConfig.getOpenUserInfoUrl(), accessToken, openId);
		//获取access_token
		Map<String, Object> baseUserMap = HttpUtils.doGet(userInfoUrl);

		if (baseUserMap == null || baseUserMap.isEmpty()) {
			return null;
		}
		log.info("**********************************baseUserMap={}", JSON.toJSON(baseUserMap));
		String nickname = (String) baseUserMap.get("nickname");

		//Double sexTemp  = (Double) baseUserMap.get("sex");
		//int sex = sexTemp.intValue();
		String province = (String) baseUserMap.get("province");
		String city = (String) baseUserMap.get("city");
		String country = (String) baseUserMap.get("country");
		String headimgurl = (String) baseUserMap.get("headimgurl");
		StringBuilder sb = new StringBuilder(country).append("||").append(province).append("||").append(city);
		String finalAddress = sb.toString();
		try {
			//解决乱码
			nickname = new String(nickname.getBytes("ISO-8859-1"), "UTF-8");
			finalAddress = new String(finalAddress.getBytes("ISO-8859-1"), "UTF-8");

		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		if (StringUtils.isEmpty(user.getNick())) {
			user.setNick(nickname);
		}
		if (StringUtils.isEmpty(user.getPhotoUrl())) {
			user.setPhotoUrl(headimgurl);
		}
		//user.setAddressCityCode(finalAddress);
		user.setOpenId(openId);
		user.setWechatNick(nickname);
		user.setUpdateTime(new Date());
		this.baseMapper.updateById(user);
		return user;
	}

	@Override
	public int addViews(Long userId) {
		return this.baseMapper.addViews(userId);
	}

	@Override
	public int updateUserInfo(UserInfo userInfo) {
		return this.baseMapper.updateById(userInfo);
	}

	@Override
	public Long findUserByPhoneOrNameOrEmail(String username) {
		return this.baseMapper.findUserByPhoneOrNameOrEmail(username);
	}

	/**
	 * 解密
	 *
	 * @param encryptedText
	 * @return
	 */
	public String decode(String encryptedText) {
		String password = "0123456789ABCDEF0123456789ABCDEF"; // 解密密码
		try {
			// Base64 解码密文
			Security.addProvider(new BouncyCastleProvider());

			// Base64 解码密文
			byte[] decodedBytes = Base64.getDecoder().decode(encryptedText);

			// 创建 AES 密钥规范
			SecretKeySpec secretKey = new SecretKeySpec(password.getBytes(StandardCharsets.UTF_8), "AES");

			// 创建 AES 解密器，并设置 ECB 模式和 PKCS7 填充方式
			Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");
			cipher.init(Cipher.DECRYPT_MODE, secretKey);

			// 解密
			byte[] decryptedBytes = cipher.doFinal(decodedBytes);
			String decryptedText = new String(decryptedBytes, StandardCharsets.UTF_8);

			return decryptedText;
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (NoSuchProviderException e) {
			e.printStackTrace();
		}
		return null;
	}
}
